#define _GNU_SOURCE

#include "syscore.h"
#include <time.h>
#include "apis.h"
#include "common.h"
#include "modules.h"

#include <sys/sysinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <mntent.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/io.h>
#include <fcntl.h>

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include "../logServer/clogger.h"
#define SYSMLogDebug(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_DEBUG, fmt, ##args);
#define SYSMLogInfo(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_INFO, fmt, ##args);
#define SYSMLogNotice(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_NOTICE, fmt, ##args);
#define SYSMLogWarning(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_WARNING, fmt, ##args);
#define SYSMLogError(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_ERR, fmt, ##args);
#define SYSMLogCrit(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_CRIT, fmt, ##args);
#define SYSMLogAlert(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_ALERT, fmt, ##args);
#define SYSMLogEmerg(fmt, args...) CLogger(MODULE_SYSTEM, __FILE__, __LINE__, LOG_EMERG, fmt, ##args);

extern char *builddate;
extern char *buildtime;
extern char *compilerversion;

extern char *hardwareVer;
extern char *currentSoftVer;
extern char *originalSoftVer;
extern char *currVerNum ;

enum devtype_idx  {
    NF100G01A = 0,
    NF100G01B,
    NF100G02
};

char *dev_desc[] = {
"NF-100G-01A",
"NF-100G-01B",
"NF-100G-02"
};

typedef struct tagCLIENTDESC {
    struct tagCLIENTDESC *Next;
    U16 ID;
    BOOL active;
    U32 lasttime;
}CLIENTDESC;

typedef struct tagGLIST {
    CLIENTDESC* head;
    CLIENTDESC* tail;
    U32 count;
    SYS_lock_t lock;
} GLIST;

typedef struct tagREBOOTCFG{
    S32 hour;
    S32 minute;
} REBOOTCFG;

#define SYSM_TIMER_PERIOD 1000
#define SYSM_MAX_IDLE_TIME 30000
#define SYSM_HAERTBEAT_INTERVAL 5000
#define SYSM_TIMER_INTERVAL 5000
#define SYSM_PRINT_INTERVAL 30000
#define SYSM_STATUS_INTERVAL 5000
#define SYSM_REBOOT_STEP1_TIME 6000
#define SYSM_REBOOT_STEP2_TIME 4000

#define SYSM_REBOOT_INTERVAL   10000
CLIENTDESC gClientDesc[0x1000] = {{0}};
GLIST gActiveClient = {0};  
REBOOTCFG rebootCfg = {0, 0}; 
void* pSYSMTimer = NULL;
void* pSYSMPrintTimer = NULL;
void* pSYSMStatusTimer = NULL;
void* pRebootIntval = NULL;
void* pHeartBeatTimer = NULL;
typedef struct tagDEVINFO {
    U32 DevType;
    U8 MAC[6];
    U32 IP;

} DEVINFO;

#define MAX_PA  11

typedef struct tagPASTATUS {
	U8 ID;
	U8 state;
    S8 temp;
 	U8 upatt;
	U8 dnatt;
	S8 dn_power;
	S16 dn_10_power;
	S8 sw10ratio; 	
	S8 tempthreshold;
	S8 powerthreshold;
}PASTATUS;


typedef struct tagPASTATUSUP {
    U32 mask;
    PASTATUS status;
} PASTATUSUP;

#define PA_STATUS_MASK_ID       (1<<0) 
#define PA_STATUS_MASK_STATE    (1<<1) 
#define PA_STATUS_MASK_TEMP     (1<<2) 
#define PA_STATUS_MASK_UPATT    (1<<3) 
#define PA_STATUS_MASK_DNATT    (1<<4) 
#define PA_STATUS_MASK_DN_POWER     (1<<5) 
#define PA_STATUS_MASK_DN_10_POWER      (1<<6) 
#define PA_STATUS_MASK_SW10RATIO     (1<<7) 
#define PA_STATUS_MASK_TEMPTHRES	 (1<<8)
#define PA_STATUS_MASK_POWERTHRES	 (1<<9)


typedef struct tagDevStatus {
    U32 gpsStatus;
    GPSPOSITION gpsPosition;
    U32 gsmWirelessState;
    U32 gsmSnifferState;
    PASTATUS paStatus[MAX_PA];
}DEVSTATUS;

typedef struct tagSYSTATUS {
    U64 uptime;
    U32 dev_temp;
    U32 cpu_usage;
    U32 mem_usage;
    U32 data_disk_usage;
    S32 sysTemp;
}SYSSTATUS;

typedef struct {
    char port[8];
    char user[128];
    char password[128];
    char serverAddr[128];
} REMOTE_SSH;

typedef struct tagSysCPUInfo {
//char name[10];
unsigned long user;
unsigned long nic;
unsigned long system;
unsigned long idle;
} SysCPUInfo;

DEVINFO gDevInfo = {0};
SYSSTATUS gSysStatus = {0};

DEVSTATUS gDevStatus = {0,{0},0,0,{{0},{0},{0},{0},{0},{0},{0}, {0}, {0}, {0}, {0}}};

static SysCPUInfo currentcpuinfo = {0};
static SysCPUInfo previouscpuinfo = {0};

char* data_storage_path = "/mnt/usr";
S32 systemp_alert_threshold = 70;

BOOL eth1valid = FALSE;
U8 eth1mac[6];
char  OsVersion[128];

ERROR_CODE SYSM_decodeTimestamp(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeDelay(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeLogLevel(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeDebugLevel(void *h, U8* paraValue, U32 paraLength );

ERROR_CODE SYSM_decodeWirelessState(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeSnifferState(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeGPSPosition(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeGPSStatus(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeTemperature(void *h, U8* paraValue, U32 paraLength );

ERROR_CODE SYSM_decodePAAddr(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePAState(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePATemp(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePAUpatt(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePADnatt(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePADnpower(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePADn10power(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePASw10ratio(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePATempthreshold(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodePAPowerthreshold(void *h, U8* paraValue, U32 paraLength );

ERROR_CODE SYSM_decodeRebootHour(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeRebootMinute(void *h, U8* paraValue, U32 paraLength );

ERROR_CODE SYSM_decodeRemoteSshServerAddr(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeRemoteSshPort(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeRemoteSshUser(void *h, U8* paraValue, U32 paraLength );
ERROR_CODE SYSM_decodeRemoteSshPassword(void *h, U8* paraValue, U32 paraLength );


#define INVALID_LOG_LEVEL 0x100000000ULL
typedef struct tagSYSMPARAS {
    U64 time;
    U32 delay;
    U64 loglevel;
    U64 debuglevel;
}SYSMPARAS;
SYSMPARAS sysmParas = {0};
U16 rebootCmdIdx = 0;
U16 rebootSrc = 1;

PARADECODERMAP sysmParaTab[] = {
    {PARA_TYPE_TIMESTAMP,SYSM_decodeTimestamp }, 
    {PARA_TYPE_DELAY,SYSM_decodeDelay }, 
    {PARA_TYPE_SYS_LOG_LEVEL,SYSM_decodeLogLevel },
    {PARA_TYPE_SYS_DEBUG_LEVEL,SYSM_decodeDebugLevel }
};


PARADECODERMAP devStatusTab[] = {
        {PARA_TYPE_GSM_WILELESS_STATE,SYSM_decodeWirelessState},
        {PARA_TYPE_GSM_SNIFFER_STATE, SYSM_decodeSnifferState},
        {PARA_TYPE_GPS_STATUS,SYSM_decodeGPSStatus},
        {PARA_TYPE_GPS_COORDINATE,SYSM_decodeGPSPosition},
        {PARA_TYPE_PA_ADDR,SYSM_decodePAAddr},
		{PARA_TYPE_PA_STATE,SYSM_decodePAState},
		{PARA_TYPE_PA_TEMP,SYSM_decodePATemp},
		{PARA_TYPE_UP_ATT,SYSM_decodePAUpatt},
		{PARA_TYPE_DN_ATT,SYSM_decodePADnatt},
		{PARA_TYPE_PA_DN_POWER,SYSM_decodePADnpower},
		{PARA_TYPE_PA_DN_10_POWER,SYSM_decodePADn10power},
        {PARA_TYPE_PA_10_SWR,SYSM_decodePASw10ratio},
        {PARA_TYPE_PA_TEMP_THRESHOLD, SYSM_decodePATempthreshold},
        {PARA_TYPE_PA_POWER_THRESHOLD, SYSM_decodePAPowerthreshold}
}; 

PARADECODERMAP sysTempTab[] = {
        {PARA_TYPE_SYS_TEMPERATURE, SYSM_decodeTemperature}

};

PARADECODERMAP rebootTab[] = {
        {PARA_TYPE_SYS_REBOOT_HOUR, SYSM_decodeRebootHour},
        {PARA_TYPE_SYS_REBOOT_MINUTE, SYSM_decodeRebootMinute}
};

PARADECODERMAP remoteSshTab[] = {
        {PARA_TYPE_SYS_REMOTE_SSH_PORT, SYSM_decodeRemoteSshPort},
        {PARA_TYPE_SYS_REMOTE_SSH_USER, SYSM_decodeRemoteSshUser},
        {PARA_TYPE_SYS_REMOTE_SSH_PASSWORD, SYSM_decodeRemoteSshPassword},
        {PARA_TYPE_SYS_REMOTE_SSH_SERVERIP, SYSM_decodeRemoteSshServerAddr}
};


ERROR_CODE SYSM_decodePAAddr(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        U8 id = *((U8*)paraValue);

            paStatusUp->mask |= PA_STATUS_MASK_ID;
            paStatusUp->status.ID = id;            
            return PARA_VALUE_ERROR_NO_ERROR;

    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePAState(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        U8 state = *((U8*)paraValue);
        if(state < 2 )
        {
            paStatusUp->mask |= PA_STATUS_MASK_STATE;
            paStatusUp->status.state = state;            
            return PARA_VALUE_ERROR_NO_ERROR;
        }
        else
        {
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        }  
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePATemp(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(S8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_TEMP;
        paStatusUp->status.temp = *((S8*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePAUpatt(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_UPATT;
        paStatusUp->status.upatt= *((U8*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePADnatt(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_DNATT;
        paStatusUp->status.dnatt= *((U8*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePADnpower(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_DN_POWER;
        paStatusUp->status.dn_power= *((U8*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePADn10power(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == (sizeof(U8)*2))
    {
        paStatusUp->mask |= PA_STATUS_MASK_DN_10_POWER;
        paStatusUp->status.dn_10_power= *((int16_t *)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}


ERROR_CODE SYSM_decodePASw10ratio(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_SW10RATIO;
        paStatusUp->status.sw10ratio= *((U8*)paraValue);

        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePATempthreshold(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_TEMPTHRES;
        paStatusUp->status.tempthreshold = *((U8*)paraValue);

        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodePAPowerthreshold(void *h, U8* paraValue, U32 paraLength )
{
    PASTATUSUP *paStatusUp = (PASTATUSUP*)h;
    
    if(paraLength == sizeof(U8))
    {
        paStatusUp->mask |= PA_STATUS_MASK_POWERTHRES;
        paStatusUp->status.powerthreshold= *((U8*)paraValue);

        return PARA_VALUE_ERROR_NO_ERROR;
        
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}


ERROR_CODE SYSM_decodeTemperature(void *h, U8* paraValue, U32 paraLength )
{
    if(paraLength == sizeof(S32))
    {
        S32 temp = *((S32*)paraValue);
        if((temp >= -128) && (temp <= 127))
        {
            *((S32*)h) = temp;            
            return PARA_VALUE_ERROR_NO_ERROR;
        }
        else
        {
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        }  
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }

}

ERROR_CODE SYSM_decodeGPSStatus(void *h, U8* paraValue, U32 paraLength )
{
    DEVSTATUS* buff = (DEVSTATUS*)h;

    if(paraLength == sizeof(U32))
    {
        buff->gpsStatus = *((U32*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
}

ERROR_CODE SYSM_decodeGPSPosition(void *h, U8* paraValue, U32 paraLength )
{
    DEVSTATUS* buff = (DEVSTATUS*)h;

    if(paraLength == sizeof(GPSPOSITION))
    {
        memcpy(&buff->gpsPosition , paraValue,sizeof(GPSPOSITION));
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
}



ERROR_CODE SYSM_decodeWirelessState(void *h, U8* paraValue, U32 paraLength )
{
    DEVSTATUS* buff = (DEVSTATUS*)h;

    if(paraLength == sizeof(U32))
    {
        buff->gsmWirelessState= *((U32*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeSnifferState(void *h, U8* paraValue, U32 paraLength )
{
    DEVSTATUS* buff = (DEVSTATUS*)h;

    if(paraLength == sizeof(U32))
    {
        buff->gsmSnifferState= *((U32*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}


ERROR_CODE SYSM_decodeTimestamp(void *h, U8* paraValue, U32 paraLength )
{
    SYSMPARAS* buff = (SYSMPARAS*)h;

    if(paraLength == sizeof(U64))
    {
        U64 time = *((U64*)paraValue);
        if(time > 0 )
        {
            buff->time= time;
            return PARA_VALUE_ERROR_NO_ERROR;
        }
        else
        {
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        }
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeDelay(void *h, U8* paraValue, U32 paraLength )
{
    SYSMPARAS* buff = (SYSMPARAS*)h;

    if(paraLength == sizeof(U32))
    {
        buff->delay= *((U32*)paraValue);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeLogLevel(void *h, U8* paraValue, U32 paraLength )
{
    SYSMPARAS* buff = (SYSMPARAS*)h;

    if(paraLength == sizeof(U32))
    {
        U32 level = *((U32*)paraValue);
        if(level <= LOG_MAX_LEVEL)
        {   
            buff->loglevel= level;
            return PARA_VALUE_ERROR_NO_ERROR;
        }
        else
        {
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        }
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeDebugLevel(void *h, U8* paraValue, U32 paraLength )
{
    SYSMPARAS* buff = (SYSMPARAS*)h;

    if(paraLength == sizeof(U32))
    {
        U32 level = *((U32*)paraValue);
        if(level <= DEBUG_MAX_LEVEL)
        {   
            buff->debuglevel= level;
            return PARA_VALUE_ERROR_NO_ERROR;
        }
        else
        {
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        }
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}


ERROR_CODE SYSM_decodeRebootHour(void *h, U8* paraValue, U32 paraLength )
{
    REBOOTCFG* buff = (REBOOTCFG*)h;
    SYSMLogNotice("set reboot hour is %d ",  *((U32*)paraValue));
    if(paraLength == sizeof(U32))
    {
        buff->hour= *((U32*)paraValue);
        if (buff->hour < 0 || buff->hour > 23)
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeRebootMinute(void *h, U8* paraValue, U32 paraLength )
{
    REBOOTCFG* buff = (REBOOTCFG*)h;

    if(paraLength == sizeof(U32))
    {
        buff->minute= *((U32*)paraValue);
        if (buff->minute < 0 || buff->minute > 59)
            return PARA_VALUE_ERROR_INVALID_PARAVALUE;
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeRemoteSshPort(void *h, U8* paraValue, U32 paraLength )
{
    REMOTE_SSH* buff = (REMOTE_SSH*)h;

    if(paraLength > 0)
    {
        memcpy(buff->port, paraValue, paraLength);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeRemoteSshUser(void *h, U8* paraValue, U32 paraLength )
{
    REMOTE_SSH* buff = (REMOTE_SSH*)h;

    if(paraLength > 0)
    {
        memcpy(buff->user, paraValue, paraLength);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeRemoteSshPassword(void *h, U8* paraValue, U32 paraLength )
{
    REMOTE_SSH* buff = (REMOTE_SSH*)h;

    if(paraLength > 0)
    {
        memcpy(buff->password, paraValue, paraLength);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}

ERROR_CODE SYSM_decodeRemoteSshServerAddr(void *h, U8* paraValue, U32 paraLength )
{
    REMOTE_SSH* buff = (REMOTE_SSH*)h;

    if(paraLength > 0)
    {
        memcpy(buff->serverAddr, paraValue, paraLength);
        return PARA_VALUE_ERROR_NO_ERROR;
    }
    else
    {
        return PARA_VALUE_ERROR_INVALID_PARALENGTH;
    }
    
}


RESULT SYSM_setTime(U64 time)
{
    struct timeval tmval, tmvalUtc;
    tmvalUtc.tv_sec=time - 28800;
    tmvalUtc.tv_usec=0;
   

    tmval.tv_sec=time;
    tmval.tv_usec=0;
    
    if(settimeofday (&tmvalUtc, (struct timezone *) 0) < 0)
    {
        SYSMLogError("Set system datatime error!");
        return -1;
    }
    
    system("hwclock  -u");
    system("hwclock  -w");
    
    if(settimeofday (&tmval, (struct timezone *) 0) < 0)
    {
        SYSMLogError("Set system datatime error!");
        return -1;
    }

    return RC_OK;

}

BOOL SYSM_isClientActive(U16 srcID)
{
    if(gClientDesc[srcID].active)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int32_t system_handle_remote_ssh(bool start, REMOTE_SSH *ssh)
{
    char cmd[1024] = {0};
    char buf[128]={0};

    if (start)
    {
        sprintf(cmd, "sh /usr/bin/remoteSsh.sh -p %s -U %s -P %s -d %s", ssh->port, ssh->user, ssh->password, ssh->serverAddr);
    }
    else
    {
        strcpy(cmd, "sh /usr/bin/remoteSsh.sh -s");
    }
    if (!execShellCommand(cmd, buf, 128))
    {
        SYSMLogError("remoteSsh failed");
        return -1;
    }
    if (strstr(buf, "success") != NULL)
    {
        return 0;
    }
    return -1;

}

bool collectLog()
{
    const char *cmd="sh /usr/bin/logather.sh";
    char buf[128]={0};
    if (!execShellCommand(cmd, buf, 128))
    {
        SYSMLogError("collect log failed");
        return false;
    }
    return true;
}

void SYSM_addActiveClient(U16 srcID)
{
    struct timespec currentTime;
    
    clock_gettime(CLOCK_MONOTONIC,&currentTime);
    
    gClientDesc[srcID].lasttime = currentTime.tv_sec;
    if(gClientDesc[srcID].active)
    {
        return;
    }
    else
    {
        gClientDesc[srcID].active = TRUE; 
        SYS_lock(&gActiveClient.lock);
        if(gActiveClient.count)
        {   
            CLIENTDESC *tmp = gActiveClient.tail;
            tmp->Next = &gClientDesc[srcID];
            gActiveClient.tail = &gClientDesc[srcID];
            gClientDesc[srcID].Next = NULL;
            gActiveClient.count++;
        }
        else
        {
            gActiveClient.head = gActiveClient.tail = &gClientDesc[srcID];
            gClientDesc[srcID].Next = NULL;
            gActiveClient.count = 1;
        }
        SYS_unlock(&gActiveClient.lock);
    }
}


RESULT SYSM_delActiveClient(U16 ID)
{
    if(gClientDesc[ID].active == FALSE)
    {   //already
        return RC_OK;
    }
    else
    {
        CLIENTDESC *current = NULL;
        CLIENTDESC *previous = NULL;
        CLIENTDESC *tmp;
        
        gClientDesc[ID].active = FALSE;
        
        SYS_lock(&gActiveClient.lock);
        current = gActiveClient.head;
        while(current)
        {
            if(current->ID == ID)
            {
                tmp = current->Next;

                if(tmp == NULL)
                {
                    gActiveClient.tail = previous;
                }

                if(previous)
                {
                    previous->Next = tmp;
                }
                else
                {
                   gActiveClient.head = tmp; 
                }
                
                current->active = FALSE;                    
                current->Next = NULL;
                gActiveClient.count--;

                SYS_unlock(&gActiveClient.lock);
                return RC_OK;
                
            }
            else
            {
                previous = current;
                current = current->Next;
            }

        }

        SYS_unlock(&gActiveClient.lock);
        //cant find the active client in list
        SYSMLogError("Unexpected error in active client list");
        return RC_FAIL;
    }

}

U16 SYSM_allocClientID()
{
    int i=0;
    for(i =1; i< 0x0ffe; i++)
    {
        if(gClientDesc[i].active == FALSE)
        {
            SYSM_addActiveClient(i);
            return i;
        }
    }

    return 0;
}

void SYSM_broadcastMsgToActiveClient(void (*sendmsg)(void *,U16), void* msg, U16 len)
{
    CLIENTDESC *current = NULL;
    
    if(gActiveClient.count)
    {
        SYS_lock(&gActiveClient.lock);
        current  = gActiveClient.head;
        while(current)
        {
            *((long*)msg) = current->ID;
            sendmsg(msg,len);
            current = current->Next;
        }
        SYS_unlock(&gActiveClient.lock);
    }

}

void SYSM_rebootstep2_timer(void*h)
{
    system("reboot -f");        
}

void SYSM_rebootstep1_timer(void*h)
{
    U32 rc = PARA_VALUE_RESULT_SUCCESS;
    CM_SendMsg_1Para(rebootSrc,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_SET_RESPONSE,CMD_CODE_SYS_REBOOT,rebootCmdIdx,
        PARA_TYPE_RESULT,sizeof(U32),(U8*)&rc);    
    
    MOD_timerStart(MODULE_SYSTEM,SYSM_REBOOT_STEP2_TIME,SYSM_rebootstep2_timer,NULL);
            
}

void SYSM_auto_reboot(void *h)
{   
    time_t rawtime;
    struct tm p= { 0 };
    time(&rawtime);
    localtime_r(&rawtime, &p);
    if ((p.tm_hour == rebootCfg.hour) && (p.tm_min == rebootCfg.minute) && (p.tm_sec > 35))
    {
        MOD_timerStart(MODULE_SYSTEM,SYSM_REBOOT_STEP2_TIME,SYSM_rebootstep2_timer,NULL);
        
        CM_SendMsg_noPara(MODULE_GSM_CAP, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_SET, CMD_GSM_RESTART, gCmdIndex++);
        CM_SendMsg_noPara(MODULE_CDMA_CAP, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_SET, CMD_CDMA_RESTART, gCmdIndex++);
        SYSMLogError("%s %d:%d : %d", "system reboot every day time is", p.tm_hour, p.tm_min, p.tm_sec);
    }
    if (pRebootIntval != NULL)
        MOD_timerRestart(pRebootIntval, SYSM_REBOOT_INTERVAL);   
}

void SYSM_heartbeat_timer(void* h)
{ 
    U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
    CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
        PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc);   
     
    MOD_timerRestart(pHeartBeatTimer, SYSM_HAERTBEAT_INTERVAL);
}


void SYSM_setProc(PCMDHEADER pCmd, PCMDHEADER pAck)
{
    memset(&sysmParas, 0, sizeof(SYSMPARAS));
    sysmParas.loglevel = INVALID_LOG_LEVEL;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_CLIENT_CONNECT:
            {
                PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
                if(MODULE_INTF == pMsgHdr->srcID)
                {
                    U16 id = SYSM_allocClientID();
                    if(id)
                    {
                        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_SYS_CLIENT_ID,id);
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_CANNOT_GET_ID);
                    }
                }
                else
                {   //already has an ID, do nothing
                    pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_SYS_CLIENT_ID,pMsgHdr->srcID);

                }
                
            }
            break;
        case CMD_CODE_CLIENT_DISCONNECT:
            {
                PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
                if(MODULE_INTF != pMsgHdr->srcID)
                { 
                    SYSM_delActiveClient(pMsgHdr->srcID);
                    pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                }
                else
                {
                    pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_ILLEGAL_SRC);

                }
            } 
            break;
        case CMD_CODE_LOG_LEVEL:
            sysmParas.loglevel = INVALID_LOG_LEVEL;
            if(RC_OK == CM_paraListDecoder(pCmd,pAck, sysmParaTab,sizeof(sysmParaTab)/sizeof(PARADECODERMAP),&sysmParas,FALSE))
            {
                if(sysmParas.loglevel != INVALID_LOG_LEVEL)
                {
                    //if(RC_OK == SYS_setLogLevel(sysmParas.loglevel))
                    //user logserver to replace syslog
                    if(RC_OK == CSetLogLevel(sysmParas.loglevel))
                    {
                        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_INVALID_PARAVALUE);
                    }
                }
                else
                {
                    pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_NOT_ENOUGH_PARA);

                }
            }
            break;
        case CMD_CODE_DEBUG_LEVEL:
            sysmParas.debuglevel = INVALID_LOG_LEVEL;
            if(RC_OK == CM_paraListDecoder(pCmd,pAck, sysmParaTab,sizeof(sysmParaTab)/sizeof(PARADECODERMAP),&sysmParas,FALSE))
            {
                if(sysmParas.debuglevel != INVALID_LOG_LEVEL)
                {
                    if(RC_OK == SYS_setDebugLevel(sysmParas.debuglevel))
                    {
                        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_INVALID_PARAVALUE);
                    }
                }
                else
                {
                    pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_NOT_ENOUGH_PARA);

                }
            }
            break;
        case CMD_CODE_SYS_REBOOT:
            {
                sysmParas.delay = 0;
                if(RC_OK == CM_paraListDecoder(pCmd,pAck, sysmParaTab,sizeof(sysmParaTab)/sizeof(PARADECODERMAP),&sysmParas,FALSE))
                {
                    PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
                    rebootCmdIdx = pCmd->cmdIndex;
                    rebootSrc = pMsgHdr->srcID;
                    if (rebootSrc == MODULE_INTF)
                    {
                        createRestartCauseFileByCode(SYSTEM_MANUAL_RESTRAT);
                        saveImportantLog("server control device reboot");
                    }
                    else if (rebootSrc == MODULE_CLI)
                    {
                        saveImportantLog("reset device by cli");
                        createRestartCauseFileByCode(SYSTEM_MANUAL_RESTRAT);
                    }
                    else
                    {
                        createRestartCauseFileByCode(SYSTEM_SOFT_RESTART);
                    }
                    CM_SendMsg_noPara(MODULE_PA,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_REBOOT,gCmdIndex++);
                    CM_SendMsg_noPara(MODULE_SMS,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_REBOOT,gCmdIndex++);
                    CM_SendMsg_noPara(MODULE_PM, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_SYS_REBOOT, gCmdIndex++);
                    CM_SendMsg_noPara(MODULE_GSM_CAP, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_SET, CMD_GSM_RESTART, gCmdIndex++);
                    CM_SendMsg_noPara(MODULE_CDMA_CAP, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_SET, CMD_CDMA_RESTART, gCmdIndex++);
                    CM_SendMsg_noPara(MODULE_SYSMONITOR, MODULE_SYSTEM,MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_STOP, gCmdIndex++);
                    pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_DOING);
                    MOD_timerStart(MODULE_SYSTEM,SYSM_REBOOT_STEP1_TIME,SYSM_rebootstep1_timer,NULL);
                }
 
            }
            break;

        case CMD_CODE_SYS_COLLECT_LOG:
            if (collectLog())
            {
                 pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_DOING);
            }
            else
            {
                 pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_FAILED);
            }
            break;

        case CMD_CODE_SYS_TIME_SYNC:
            {   
                sysmParas.time =0;
                if(RC_OK == CM_paraListDecoder(pCmd,pAck, sysmParaTab,sizeof(sysmParaTab)/sizeof(PARADECODERMAP),&sysmParas,FALSE))
                {
                    if(sysmParas.time != 0)
                    {
                        
                        if(RC_OK == SYSM_setTime(sysmParas.time))
                        {	
                            CM_SendMsg_noPara(MODULE_GSM_CAP,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_TIME_SYNC,gCmdIndex++);
                            CM_SendMsg_noPara(MODULE_CDMA_CAP,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_TIME_SYNC,gCmdIndex++);
                            CM_SendMsg_noPara(MODULE_WCDMA_CAP,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_TIME_SYNC,gCmdIndex++);
                            CM_SendMsg_noPara(MODULE_TDSCDMA_CAP,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_TIME_SYNC,gCmdIndex++);
                            CM_SendMsg_noPara(MODULE_WIFI,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_TIME_SYNC,gCmdIndex++);
                            pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                        }
                        else
                        {
                            
                            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_GENERAL_ERROR);
                        }
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_NOT_ENOUGH_PARA);
                    }
                }
            }
            break;
         case CMD_CODE_SYS_SLEEP:
            {
                //CM_SendMsg_noPara(MODULE_PA,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_SLEEP,0);
               // CM_SendMsg_noPara(MODULE_GSM_CAP,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_SLEEP,gCmdIndex++);                
                pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
            }
            break;
            
         case CMD_CODE_SYS_WAKE:
            {
                //CM_SendMsg_noPara(MODULE_PA,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_WAKE,0);
              //  CM_SendMsg_noPara(MODULE_GSM_CAP,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_WAKE,gCmdIndex++);                
                pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
            }
            break;
        case CMD_CODE_SYS_REBOOT_ON:
            {   
                REBOOTCFG rebootParas = {0, 0};
                if(RC_OK == CM_paraListDecoder(pCmd,pAck, rebootTab,sizeof(rebootTab)/sizeof(PARADECODERMAP),&rebootParas,FALSE))
                {
                    if (rebootParas.hour >= 0 && rebootParas.hour <= 23)
                    {
                        rebootCfg.hour = rebootParas.hour;
                    }
                    if (rebootParas.minute >= 0 && rebootParas.minute <= 59)
                    {
                        rebootCfg.minute = rebootParas.minute;
                    }

                }
                else
                {
                     pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_GENERAL_ERROR);
                }
                
                if (pRebootIntval == NULL)
                    pRebootIntval = MOD_timerStart(MODULE_SYSTEM, SYSM_REBOOT_INTERVAL, SYSM_auto_reboot, NULL);
                pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                SYSMLogNotice("start timer to reboot system at time %02d:%02d", rebootCfg.hour, rebootCfg.minute);
            }
            break;                

        case CMD_CODE_SYS_REBOOT_OFF:
            {   
                pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                SYSMLogNotice("stop timer to reboot system");
                pRebootIntval = NULL;
            }
            break;         

        case CMD_CODE_SYS_ALERT_TEMP_THRESHOLD:
            {
                S32 threshold = 256;
                if(RC_OK == CM_paraListDecoder(pCmd,pAck, sysTempTab,sizeof(sysTempTab)/sizeof(PARADECODERMAP),&threshold,FALSE))
                {
                    if(threshold != 256)
                    {
                        systemp_alert_threshold = threshold;  
                        pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                    }
                    else
                    {
                        pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_NOT_ENOUGH_PARA);

                    }
                }
            }
            break;

        case CMD_CODE_SYS_SSH_ON:
            {   
                REMOTE_SSH remoteSsh;
                int32_t ret = -1;
                memset(&remoteSsh, 0, sizeof(REMOTE_SSH));
                if(RC_OK == CM_paraListDecoder(pCmd,pAck, remoteSshTab,sizeof(remoteSshTab)/sizeof(PARADECODERMAP),&remoteSsh,FALSE))
                {
                    ret = system_handle_remote_ssh(true, (REMOTE_SSH *)&remoteSsh);
                }
                if (ret == 0)
                {
                    pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
                }
                else 
                {   
                    pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1),PARA_VALUE_ERROR_GENERAL_ERROR);
                }
                SYSMLogNotice("start remotessh %s %s %s %s ret %d" , remoteSsh.port, remoteSsh.user, remoteSsh.password, remoteSsh.serverAddr, ret);
            }
            break;                

        case CMD_CODE_SYS_SSH_OFF:
            pAck->cmdLength = CM_paraPackU32((PPARAM)(pAck+1),PARA_TYPE_RESULT,PARA_VALUE_RESULT_SUCCESS);
            system_handle_remote_ssh(false, NULL);
            SYSMLogNotice("stop remote ssh");
            break;


//here is test heartbeat
#ifdef MODULE_TEST
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            SYSMLogError("----- test module system ----- %04x", CMD_CODE_SYSMONITOR_TEST_MODULE);
            while(1)
            {

            }
            break;
#endif

        default:
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_UNKNOWN_CMDCODE);
            SYSMLogError("Unknown SET cmd cmdCode=%04x",pCmd->cmdCode);
            break;

    }
}

void SYSM_getProc(PCMDHEADER pCmd, PCMDHEADER pAck)
{

    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BASIC_INFO:
            {
                PPARAM pParam = (PPARAM)(pAck + 1);
                U8 *pValue = NULL;

                pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_DEVICE_TYPE,strlen(dev_desc[gDevInfo.DevType])+1,&pValue);
                memcpy(pValue,dev_desc[gDevInfo.DevType],strlen(dev_desc[gDevInfo.DevType])+1);
                
                pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_SW_VERSION, strlen(currentSoftVer)+1,&pValue);
                memcpy(pValue,currentSoftVer,strlen(currentSoftVer)+1);
                
                pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_SW_BUILDDATE, strlen(builddate)+1,&pValue);
                memcpy(pValue,builddate,strlen(builddate)+1);
                
                pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_SW_BUILDTIME, strlen(buildtime)+1,&pValue);
                memcpy(pValue,buildtime,strlen(buildtime)+1);
                
                pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_SW_COMPILER_VERSION, strlen(compilerversion)+1,&pValue);
                memcpy(pValue,compilerversion,strlen(compilerversion)+1);
                
                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_SYS_OS_VERSION, strlen(OsVersion)+1, &pValue);
                memcpy(pValue, OsVersion, strlen(OsVersion) + 1);

                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_SYS_HW_VERSION, strlen(hardwareVer)+1, &pValue);
                memcpy(pValue, hardwareVer, strlen(hardwareVer) + 1);
               
                pAck->cmdLength += CM_paraPackPara(&pParam,  PARA_TYPE_SYS_SW_ORIGINAL_VERSION , strlen(originalSoftVer)+1, &pValue);
                memcpy(pValue, originalSoftVer, strlen(originalSoftVer) + 1);

                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_SYS_SW_CURRVERNUM, strlen(currVerNum)+1, &pValue);
                memcpy(pValue, currVerNum, strlen(currVerNum) + 1);

                if(eth1valid)               
                {                
                    pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_MAC_ADDR, 6, &pValue);
                    memcpy(pValue,eth1mac,6);
                }
                
                //pAck->cmdLength += CM_paraPackPara(&pParam,PARA_TYPE_SYS_IP_ADDR, sizeof(),&pValue);
                
            }
            break;
        case CMD_CODE_SYS_STATUS:
            {
                PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
                PPARAM pParam = (PPARAM)(pAck + 1);
                U8 *pValue = NULL;

                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_SYS_CPU_USAGE, sizeof(U32),&pValue);
                memcpy(pValue,&gSysStatus.cpu_usage, sizeof(U32));
                
                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_SYS_MEM_USAGE, sizeof(U32),&pValue);
                memcpy(pValue,&gSysStatus.mem_usage, sizeof(U32));

                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_DATA_STORAGE_USAGE, sizeof(U32),&pValue);
                memcpy(pValue,&gSysStatus.data_disk_usage, sizeof(U32));

                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_SYS_TEMPERATURE, sizeof(S32),&pValue);
                memcpy(pValue,&gSysStatus.sysTemp, sizeof(S32));
#if 0
                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_GSM_WILELESS_STATE, sizeof(U32),&pValue);
                memcpy(pValue,&gDevStatus.gsmWirelessState, sizeof(U32));

                pAck->cmdLength += CM_paraPackPara(&pParam, PARA_TYPE_GSM_SNIFFER_STATE, sizeof(U32),&pValue);
                memcpy(pValue,&gDevStatus.gsmSnifferState, sizeof(U32));
#endif
                pAck->cmdLength +=CM_paraPackPara(&pParam, PARA_TYPE_GPS_STATUS, sizeof(U32),&pValue);
                memcpy(pValue,&gDevStatus.gpsStatus, sizeof(U32));

                pAck->cmdLength +=CM_paraPackPara(&pParam, PARA_TYPE_GPS_COORDINATE, sizeof(GPSPOSITION),&pValue);
                memcpy(pValue,&gDevStatus.gpsPosition, sizeof(GPSPOSITION));

                pAck->cmdLength +=CM_paraPackPara(&pParam, PARA_TYPE_SYS_PASTATUS, (sizeof(PASTATUS) * MAX_PA),&pValue);
                memcpy(pValue,&gDevStatus.paStatus, (sizeof(PASTATUS) * MAX_PA));
 

                SYSM_addActiveClient(pMsgHdr->srcID);
                               
            }
            break;
        default:
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_UNKNOWN_CMDCODE);
            SYSMLogError("Unknown GET cmd cmdCode=%04x",pCmd->cmdCode);
            break;

    }
}

void SYSM_eventProc(PCMDHEADER pCmd)
{
    
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_CLIENT_HEARTBEAT:
            {
                PMSGHEADER pMsgHdr = (PMSGHEADER)((U8*)pCmd - sizeof(MSGHEADER));
                SYSM_addActiveClient(pMsgHdr->srcID);
            }
            break;
        case CMD_GSM_EVT_STATUS:
            {
                CM_paraListDecoder(pCmd,NULL,devStatusTab,sizeof(devStatusTab)/sizeof(PARADECODERMAP),&gDevStatus,TRUE);                
            }
            break;
        case CMD_CDMA_EVT_STATUS:
            {
                CM_paraListDecoder(pCmd,NULL,devStatusTab,sizeof(devStatusTab)/sizeof(PARADECODERMAP),&gDevStatus,TRUE);                
            }
            break;

        case CMD_CODE_GPS_STATUS:
            {
                CM_paraListDecoder(pCmd,NULL,devStatusTab,sizeof(devStatusTab)/sizeof(PARADECODERMAP),&gDevStatus,TRUE);                
            }
            break;
		case CMD_EVT_PA_STATUS:
            {
                PASTATUSUP paStatusUpdate;
                paStatusUpdate.mask = 0;
                if( RC_OK == CM_paraListDecoder(pCmd,NULL,devStatusTab,sizeof(devStatusTab)/sizeof(PARADECODERMAP),&paStatusUpdate,TRUE))
                {
                    if(paStatusUpdate.mask & PA_STATUS_MASK_ID)
                    {
                        U8 id = (paStatusUpdate.status.ID - 1);
                        PASTATUS* pStatus = &gDevStatus.paStatus[id];
                        pStatus->ID = id;
                       
                        if(paStatusUpdate.mask & PA_STATUS_MASK_STATE)
                        {
                            pStatus->state = paStatusUpdate.status.state;
							
							if(paStatusUpdate.mask & PA_STATUS_MASK_TEMP)
                            {
                            	pStatus->temp = paStatusUpdate.status.temp;
							
                            	if(paStatusUpdate.mask & PA_STATUS_MASK_UPATT)
                                pStatus->upatt = paStatusUpdate.status.upatt;          
                            
								if(paStatusUpdate.mask & PA_STATUS_MASK_DNATT)
                                pStatus->dnatt= paStatusUpdate.status.dnatt;

                            	if(paStatusUpdate.mask & PA_STATUS_MASK_DN_POWER)
                                pStatus->dn_power= paStatusUpdate.status.dn_power;
                            
                            	if(paStatusUpdate.mask & PA_STATUS_MASK_DN_10_POWER)
                                pStatus->dn_10_power= paStatusUpdate.status.dn_10_power;

                            	if(paStatusUpdate.mask & PA_STATUS_MASK_SW10RATIO)
                            	{
                                	pStatus->sw10ratio = paStatusUpdate.status.sw10ratio;
                            	}
								if(paStatusUpdate.mask & PA_STATUS_MASK_TEMPTHRES)
									pStatus->tempthreshold = paStatusUpdate.status.tempthreshold;
								if(paStatusUpdate.mask & PA_STATUS_MASK_POWERTHRES)
									pStatus->powerthreshold = paStatusUpdate.status.powerthreshold;
							}                        
						}                    
					}
                }            
			}
            break;		


        default:
            SYSMLogError("Unknown EVENT cmdCode=%04x",pCmd->cmdCode);            
            break;
    }
}

void SYSM_setAckProc(PCMDHEADER pCmd)
{
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_SYS_REBOOT:
        {   
           
        }
        
        default:
            //pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_UNKNOWN_CMDCODE);
            SYSMLogError("Unknown SET Ack cmd cmdCode=%04x",pCmd->cmdCode);
        break;

    }
}

void SYSM_getAckProc(PCMDHEADER pCmd, PCMDHEADER pAck)
{
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BASIC_INFO:
            {
                


            }
        default:
            pAck->cmdLength = CM_paraPackError((PPARAM)(pAck+1), PARA_VALUE_ERROR_UNKNOWN_CMDCODE);
            SYSMLogError("Unknown GET Ack cmd cmdCode=%04x",pCmd->cmdCode);
            break;

    }
}

void SYSM_print_timer(void *h)
{
    MSG_printStats();
    MSGPROC_printStats();       
    DATAPROC_printStats();
    DATASTOR_printStats();

    dbgprintf(DEBUG_INFO,stdout,"CPU usage:%d,   MEM usage:%d Data Storage usage: %d\n",gSysStatus.cpu_usage,gSysStatus.mem_usage, gSysStatus.data_disk_usage);
    MOD_timerRestart(pSYSMPrintTimer,SYSM_PRINT_INTERVAL);
}


void SYSM_timer(void *h)
{
    CLIENTDESC *current = NULL;
    CLIENTDESC *previous = NULL;
    CLIENTDESC *tmp;
    struct timespec currenTime;
    U32 currentSec = 0;
    clock_gettime(CLOCK_MONOTONIC,&currenTime);
    currentSec = currenTime.tv_sec;

  
    SYS_lock(&gActiveClient.lock);

    current = gActiveClient.head;
    while (current)
    {
        if( (current->ID > 1)
             && ((currentSec - current->lasttime) > SYSM_MAX_IDLE_TIME) )
        {
            //timeout, remove this one
            tmp = current->Next;
            current->active = FALSE;                    
            current->Next = NULL;
            gActiveClient.count--;
            
            if(tmp == NULL)
            {
                gActiveClient.tail = previous;
            }

            if(previous)
            {
                previous->Next = tmp;
            }
            else
            {
               gActiveClient.head = tmp; 
            }
            
            current = tmp;
                
        }
        else
        {
            previous = current;
            current = current->Next;
        }
    }

    SYS_unlock(&gActiveClient.lock);
    
    MOD_timerRestart(pSYSMTimer,SYSM_TIMER_INTERVAL);
}

void SYSM_getHostCPUInfo(SysCPUInfo *pCpuinfo)
{
    FILE    *fd;
    char    buff[256];

    memset(buff, 0, 256);
    
    fd = fopen("/proc/stat", "r");
    fgets(buff, sizeof(buff), fd);
    fclose(fd);
    
    sscanf(buff, "%*s %lu %lu %lu %lu", &pCpuinfo->user, &pCpuinfo->nic, 
                            &pCpuinfo->system, &pCpuinfo->idle);
    
}

char * skip_token(const char *p)
{
    while (isspace(*p)) p++;
    while (*p && !isspace(*p)) p++;
    return (char *)p;
}

int SYSM_getMemUsage()
{
	int fd, len;
	char *p;
	char buffer[4096] = {0};
	unsigned long memory_stats[2] = {0, 0};
	
	fd = open("/proc/meminfo", O_RDONLY);
	if(fd < 0)
	{
		return fd;
	}

	len = read(fd, buffer, sizeof(buffer)-1);
	close(fd);

	buffer[len] = '\0';
		  
	p = buffer;
	p = skip_token(p);
	memory_stats[0] = strtoul(p, &p, 10); /* MemTotal */
	p = strchr(p, '\n');
	p = skip_token(p);
	memory_stats[1] = strtoul(p, &p, 10); /* MemFree */
	p = strchr(p, '\n');
	p = skip_token(p);
	memory_stats[1] += strtoul(p, &p, 10); /* Buffers */
	p = strchr(p, '\n');
	p = skip_token(p);
	memory_stats[1] += strtoul(p, &p, 10); /* Cached */

    //Memused = MemTotal-(MemFree+Buffers+Cached)	  
	return ((memory_stats[0]-memory_stats[1])*100/memory_stats[0]);	
}

float SYSM_calculateHostCPURate(SysCPUInfo *first, SysCPUInfo *second)
{
        unsigned long   old_CPU_Time, new_CPU_Time;
        unsigned long   usr_Time_Diff, sys_Time_Diff, nic_Time_Diff;
        float                   cpu_use = 0.0;

        old_CPU_Time = (unsigned long)(first->user + first->nic + first->system + first->idle);
        new_CPU_Time = (unsigned long)(second->user + second->nic + second->system + second->idle);

        usr_Time_Diff = (unsigned long)(second->user - first->user);
        sys_Time_Diff = (unsigned long)(second->system - first->system);
        nic_Time_Diff = (unsigned long)(second->nic -first->nic);

        if ((new_CPU_Time - old_CPU_Time) != 0)
          cpu_use = 100.0*(usr_Time_Diff + sys_Time_Diff + nic_Time_Diff)/(new_CPU_Time - old_CPU_Time);
        else
          cpu_use = 0.0;
        return cpu_use;
}


/*
 * Given a block device, find the mount table entry if that block device
 * is mounted.
 *
 * Given any other file (or directory), find the mount table entry for its
 * filesystem.
 */
struct mntent* find_mount_point(const char *name, int subdir_too)
{
	struct stat s;
	FILE *mtab_fp;
	struct mntent *mountEntry;
	dev_t devno_of_name;
	bool block_dev;

	if (stat(name, &s) != 0)
		return NULL;

	devno_of_name = s.st_dev;
	block_dev = 0;
	/* Why S_ISCHR? - UBI volumes use char devices, not block */
	if (S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode)) {
		devno_of_name = s.st_rdev;
		block_dev = 1;
	}

	mtab_fp = setmntent("/etc/mtab", "r");
	if (!mtab_fp)
		return NULL;

	while ((mountEntry = getmntent(mtab_fp)) != NULL) {
		/* rootfs mount in Linux 2.6 exists always,
		 * and it makes sense to always ignore it.
		 * Otherwise people can't reference their "real" root! */
		//if ( strcmp(mountEntry->mnt_fsname, "rootfs") == 0)
		//	continue;
        //printf("entry %p: %s %x %s %s %x %x\n",mountEntry,name,devno_of_name, mountEntry->mnt_fsname,mountEntry->mnt_dir,(stat(mountEntry->mnt_fsname, &s) == 0 )? s.st_rdev:0,(stat(mountEntry->mnt_dir, &s) == 0)?s.st_dev:0);
		if (strcmp(name, mountEntry->mnt_dir) == 0
		 || strcmp(name, mountEntry->mnt_fsname) == 0
		) { /* String match. */
			break;
		}

		if (!(subdir_too || block_dev))
			continue;

		/* Is device's dev_t == name's dev_t? */
		if (stat(mountEntry->mnt_fsname, &s) == 0 && s.st_rdev == devno_of_name)
			break;
		/* Match the directory's mount point. */
		if (stat(mountEntry->mnt_dir, &s) == 0 && s.st_dev == devno_of_name)
			break;
	}
	endmntent(mtab_fp);

	return mountEntry;
}

int SYSM_getDiskUsage()
{
    struct mntent *mount_entry = NULL;
    struct statfs s;

    const char *mount_point;

    U32 blocks_used;
    U32 blocks_percent_used;
    
    mount_entry = find_mount_point(data_storage_path,1);

    if(mount_entry == NULL)
    {
        SYSMLogError("Can't get mount entry of data storage");
        return -1;
    }

	mount_point = mount_entry->mnt_dir;

    if (statfs(mount_point, &s) != 0)
    {
        SYSMLogWarning("Can't get fs stat of data storage");
        return -1;
    }

    blocks_used = s.f_blocks - s.f_bfree;
    blocks_percent_used = 0;
    if (blocks_used + s.f_bavail) 
    {
		blocks_percent_used = (blocks_used * 100ULL
				+ (blocks_used + s.f_bavail)/2
				) / (blocks_used + s.f_bavail);
	}

    return blocks_percent_used;
}


void SYSM_status_timer(void *h)
{
    float cpu_rate;
    int df;
    int temp;
    int fd;
    int ret = 0;
    char buff[10];

    fd=open("/dev/port",O_RDWR | O_NONBLOCK);
    if(fd<0)
    {
        SYSMLogError("open /dev/port error");
    }
    else
    {
        lseek(fd,0xA45,SEEK_SET);
        buff[0]=0x2A;
        write(fd,buff,1);
        lseek(fd,0xA46,SEEK_SET);
        ret = read(fd,buff,1);
        temp = buff[0];
        close(fd);
    }

    df = SYSM_getDiskUsage();
        
    SYSM_getHostCPUInfo(&currentcpuinfo);       
    cpu_rate = SYSM_calculateHostCPURate(&previouscpuinfo,&currentcpuinfo);
    previouscpuinfo = currentcpuinfo ;

    gSysStatus.cpu_usage = (int)cpu_rate;
    gSysStatus.mem_usage = (int)SYSM_getMemUsage();

    if(df < 0)
    {
        gSysStatus.data_disk_usage = 0;
    }
    else
    {
        gSysStatus.data_disk_usage = df;
    }

    if(df > 90)
    {
        U32 steps = 1;
        CM_SendMsg_1Para(MODULE_DATAM,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_SET,CMD_CODE_OBSOLETE_PHONE_INFO,gCmdIndex++,
            PARA_TYPE_DATASTOR_OBSOLETE_STEPS, sizeof(U32), (U8*)&steps);
    }

    if(ret == 1)
    {
        
        gSysStatus.sysTemp=temp;
        if(gSysStatus.sysTemp >= systemp_alert_threshold)
        {
            CM_SendMsg_1Para(MODULE_INTF,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_ALERT_TEMP,gCmdIndex++,
                PARA_TYPE_SYS_TEMPERATURE, sizeof(S32), (U8*)&temp);
        }
    }
    MOD_timerRestart(pSYSMStatusTimer,SYSM_STATUS_INTERVAL);        
}




void* SYSM_main(void *h)
{
	CMMODINFO cmModInfo = {0};
    int i = 0;
    U32 abnormalRestart = FALSE;
    
    pthread_setname_np(pthread_self(), "system");
    memset(&gDevStatus,0,sizeof(gDevStatus));
   
    if(access("flag",0) == 0)
    {
        abnormalRestart = TRUE;
        
    }
    else
    {
        abnormalRestart = FALSE;
        system("touch flag");
    }
    
    gDevInfo.DevType = NF100G02;

    for(i=0;i<0x1000;i++)
    {
        gClientDesc[i].active =FALSE;
        gClientDesc[i].ID = i;
        gClientDesc[i].Next = NULL;
        gClientDesc[i].lasttime = 0;
    }
#ifdef LTE_DEVICE
    gDevStatus.paStatus[0].ID = 0;
    gDevStatus.paStatus[1].ID = 1;
    gDevStatus.paStatus[2].ID = 2;
    gDevStatus.paStatus[3].ID = 3;
    gDevStatus.paStatus[4].ID = 4;
    gDevStatus.paStatus[5].ID = 5;
    gDevStatus.paStatus[6].ID = 6;
#endif
    SYS_lock_init(&gActiveClient.lock);
    gActiveClient.count = 0;
    gActiveClient.head = NULL;
    gActiveClient.tail = NULL;

    //client 1  (front end) is always active 
    SYSM_addActiveClient(1);

    CM_SendMsg_1Para(MODULE_INTF,MODULE_SYSTEM,MSG_TYPE_COMMAND,CMD_EVENT,CMD_CODE_SYS_STARTUP,gCmdIndex++,
        PARA_TYPE_STARTUP_STATUS,sizeof(U32), (U8*)&abnormalRestart);
    dbgprintf(DEBUG_INFO,stdout,"System startup %s! \n",abnormalRestart?"abnormally":"normally" );
    
    pSYSMTimer = MOD_timerStart(MODULE_SYSTEM,SYSM_TIMER_INTERVAL,SYSM_timer,NULL);
    pSYSMPrintTimer= MOD_timerStart(MODULE_SYSTEM,SYSM_PRINT_INTERVAL,SYSM_print_timer,NULL);

    SYSM_getHostCPUInfo(&previouscpuinfo); 
    pSYSMStatusTimer= MOD_timerStart(MODULE_SYSTEM,SYSM_STATUS_INTERVAL,SYSM_status_timer,NULL);

    pHeartBeatTimer = MOD_timerStart(MODULE_SYSTEM, SYSM_HAERTBEAT_INTERVAL, SYSM_heartbeat_timer, NULL);
    cmModInfo.ModID = MODULE_SYSTEM;
    cmModInfo.useTimer = TRUE;
    cmModInfo.setProc = SYSM_setProc;
    cmModInfo.getProc = SYSM_getProc;
    cmModInfo.eventProc = SYSM_eventProc;
    
    CM_cmdDispatcher(&cmModInfo);

    return NULL;

}

RESULT SYSM_getMAC(char* name, U8* mac)
{
    int sockfd;
    struct ifreq tmp;   
    char mac_addr[30];

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if( sockfd < 0)
    {
        SYSMLogError("create socket fail\n", NULL);
        return RC_FAIL;
    }

    memset(&tmp,0,sizeof(struct ifreq));
    strncpy(tmp.ifr_name,name,sizeof(tmp.ifr_name)-1);
    if( (ioctl(sockfd,SIOCGIFHWADDR,&tmp)) < 0 )
    {
        SYSMLogError("mac ioctl for %s error\n",name);
        close(sockfd);
        return RC_FAIL;
    }
    close(sockfd);
        
    memcpy(mac,tmp.ifr_hwaddr.sa_data,6);

    sprintf(mac_addr, "%02x%02x%02x%02x%02x%02x",
            (unsigned char)tmp.ifr_hwaddr.sa_data[0],
            (unsigned char)tmp.ifr_hwaddr.sa_data[1],
            (unsigned char)tmp.ifr_hwaddr.sa_data[2],
            (unsigned char)tmp.ifr_hwaddr.sa_data[3],
            (unsigned char)tmp.ifr_hwaddr.sa_data[4],
            (unsigned char)tmp.ifr_hwaddr.sa_data[5]
            );
    SYSMLogError("local mac:%s\n", mac_addr);

    return RC_OK;
}

void SYSM_getOS_VERSION()
{
    FILE *fd;
    memset(OsVersion, 0, sizeof(OsVersion));

    fd = popen("uname -a","r");
    if (fd == NULL)
    {
        sprintf(OsVersion, "%s", "unknown");
        return;
    }

    if(NULL==fgets(OsVersion, sizeof(OsVersion), fd))
    {
        sprintf(OsVersion, "%s", "unknown");
        pclose(fd);
        return;
    }
    pclose(fd);
    return ;
}

RESULT SYSM_init(void)
{
    pthread_t pthrd;
    MODREG modReg = {0};        

    modReg.modID = MODULE_SYSTEM;
    modReg.needTick = TRUE;
    modReg.tickPeriod = SYSM_TIMER_PERIOD; 
    modReg.needModTimer = TRUE;
    modReg.logIdent = "SYSM";

    MOD_register(&modReg);

    SYSMLogNotice("Software Version %s %s %s\n",currentSoftVer,builddate,buildtime);

    memset(eth1mac,0,6);
    eth1valid = FALSE;
    if(SYSM_getMAC("eth1",eth1mac) == RC_OK)
    {
        eth1valid = TRUE;
    }
    SYSM_getOS_VERSION();
    if(pthread_create(&pthrd, NULL, SYSM_main, NULL) != RC_OK)
    {
        return RC_FAIL;
    } 

    return RC_OK;
}


